/*
 * Copyright (c) 2011, The Bishops Arm Project All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.  Redistributions in binary
 * form must reproduce the above copyright notice, this list of conditions and
 * the following disclaimer in the documentation and/or other materials
 * provided with the distribution.  Neither the name of the The Bishops Arm
 * Project nor the names of its contributors may be used to endorse or promote
 * products derived from this software without specific prior written
 * permission.

 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package se.joinenea.bishopsarm;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.widget.TextView;

public class PhoneOrientationHandler implements SensorEventListener {

    private final BishopsArm activity;
    private final NXTBot parent;
    private final SensorManager sm;

    private final TextView xViewO;
    private final TextView yViewO;
    private final TextView zViewO;

    private static final int LEFT_ENGINE = 0, RIGHT_ENGINE = 1;

    private static final int SENSOR_MIN_VALUE = 13, SENSOR_MAX_VALUE = 45;
    private static final int MOTOR_STOP = 0, MOTOR_MIN_VALUE = 60,
            MOTOR_MAX_VALUE = 100;
    private static final String TAG = "BishopsArm.PhoneOrientationHandler";

    public PhoneOrientationHandler(BishopsArm activity, NXTBot parent) {
        this.activity = activity;
        this.parent = parent;
        this.sm = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);;
        xViewO = (TextView) activity.findViewById(R.id.xboxo);
        yViewO = (TextView) activity.findViewById(R.id.yboxo);
        zViewO = (TextView) activity.findViewById(R.id.zboxo);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        Log.d(TAG, "onAccuracyChanged: " + sensor.getType() + ", accuracy: "
                + accuracy);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        float[] sensorValues = event.values;
        float[] motorSpeed = new float[2];

        if (!activity.isRobotConnected()) {
            return;
        }

        synchronized (this) {
            Log.d(TAG, "onSensorChanged: " + event + ", x: " + sensorValues[SensorManager.DATA_X]
                    + ", y: " + sensorValues[SensorManager.DATA_Y] + ", z: " + sensorValues[SensorManager.DATA_Z]);

            motorSpeed[LEFT_ENGINE] = sensorValues[SensorManager.DATA_Y] - sensorValues[SensorManager.DATA_Z];
            motorSpeed[RIGHT_ENGINE] = sensorValues[SensorManager.DATA_Y] + sensorValues[SensorManager.DATA_Z];

            for (int i = 0; i < 2; ++i) {
                float abs = Math.abs(motorSpeed[i]);
                float sign = Math.signum(motorSpeed[i]);

                if (abs < SENSOR_MIN_VALUE) {
                    motorSpeed[i] = MOTOR_STOP;
                } else if (abs > SENSOR_MAX_VALUE) {
                    motorSpeed[i] = MOTOR_MAX_VALUE;
                } else {
                    motorSpeed[i] =
                            MOTOR_MIN_VALUE
                                    + (MOTOR_MAX_VALUE - MOTOR_MIN_VALUE)
                                    * (abs - SENSOR_MIN_VALUE)
                                    / (SENSOR_MAX_VALUE - SENSOR_MIN_VALUE);
                }
                motorSpeed[i] *= sign;
            }

            xViewO.setText("Orientation X: " + sensorValues[SensorManager.DATA_X]);
            yViewO.setText("Orientation Y: " + sensorValues[SensorManager.DATA_Y]
                    + "  --  Motor Left:  " + motorSpeed[LEFT_ENGINE]);
            zViewO.setText("Orientation Z: " + sensorValues[SensorManager.DATA_Z]
                    + "  --  Motor Right: " + motorSpeed[RIGHT_ENGINE]);
            try {
                parent.setMotorState((int) motorSpeed[LEFT_ENGINE],
                        (int) motorSpeed[RIGHT_ENGINE]);
            } catch (Exception e) {
                activity.showMessage(e.getMessage());
                e.printStackTrace();
            }
        }
    }

    public void registerListener() {
        sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ORIENTATION),
                SensorManager.SENSOR_DELAY_GAME);
    }

    public void unregisterListener() {
        sm.unregisterListener(this,
                sm.getDefaultSensor(Sensor.TYPE_ORIENTATION));
    }

    public void stop() {
        xViewO.setText("");
        yViewO.setText("");
        zViewO.setText("");
    }

}
